package com.genghis.rapidcrm.web.view;

import com.genghis.rapidcrm.exception.RuntimeGoingException;
import com.genghis.rapidcrm.kernel.module.RapidModuleModel;
import edu.jetwinner.common.EasyStringUtil;
import freemarker.template.SimpleHash;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContextException;
import org.springframework.expression.ParseException;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.servlet.support.RequestContextUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Locale;
import java.util.Map;

/**
 * @author xulixin
 */
public abstract class RapidActionView extends RapidFreeMarkerView {

    private static final Logger log = LoggerFactory.getLogger(RapidActionView.class);

    public static final String DEFAULT_RAPIDCRM_MODULE = "Vtiger";

    private static final String RAPIDCRM_LAYOUT_VIEW_PATH = "/layout/modules/";

    protected void preProcess(HttpServletRequest request, HttpServletResponse response) throws Exception {
        preProcess(request, response, true);
    }

    abstract protected void preProcess(HttpServletRequest request, HttpServletResponse response, boolean display)
            throws Exception;

    abstract protected void postProcess(HttpServletRequest request, HttpServletResponse response)
            throws Exception;

    abstract protected void process(HttpServletRequest request, HttpServletResponse response) throws Exception;

    @Override
    protected void doRender(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response)
            throws Exception {

        exposeModelAsRequestAttributes(model, request);
        SimpleHash fmModel = buildTemplateModel(model, request, response);
        preProcess(request, response);
        if (getUrl() != null) {
            Locale locale = RequestContextUtils.getLocale(request);
            processTemplate(getTemplate(locale), fmModel, response);
        } else {
            process(request, response);
        }
        postProcess(request, response);
    }

    public void doRapidViewRender(String templateName, String module, RapidViewer viewer,
                                  HttpServletRequest request, HttpServletResponse response)
            throws Exception {

        exposeModelAsRequestAttributes(viewer.getModel(), request);
        SimpleHash fmModel = buildTemplateModel(viewer.getModel(), request, response);
        Locale locale = RequestContextUtils.getLocale(request);
        String templateUrl = getRapidViewTemplate(templateName, module, locale);
        processTemplate(getTemplate(templateUrl, locale), fmModel, response);
    }

    private String getRapidViewTemplate(String templateName, String module, Locale locale) {
        String templatePath = buildTemplateUri(templateName, DEFAULT_RAPIDCRM_MODULE);
        if (EasyStringUtil.isNotBlank(module)) {
            String moduleTemplatePath = buildTemplateUri(templateName, module);
            if (checkTemplateExists(moduleTemplatePath, locale)) {
                templatePath = moduleTemplatePath;
            }
        }
        return templatePath;
    }

    private String buildTemplateUri(String templateName, String module) {
        return RAPIDCRM_LAYOUT_VIEW_PATH + module + "/" + templateName;
    }

    private boolean checkTemplateExists(String url, Locale locale) {
        try {
            // Check that we can get the template, even if we might subsequently get it again.
            getTemplate(url, locale);
            return true;
        } catch (FileNotFoundException ex) {
            // Allow for ViewResolver chaining...
            return false;
        } catch (ParseException ex) {
            throw new ApplicationContextException("Failed to parse [" + url + "]", ex);
        } catch (IOException ex) {
            throw new ApplicationContextException("Failed to load [" + url + "]", ex);
        }
    }

    protected String getModule(HttpServletRequest request) {
        return this.getModule(request, true);
    }

    @Override
    protected String getModule(HttpServletRequest request, boolean raw) {
        String moduleName = super.getModule(request, raw);
        if (EasyStringUtil.isNotBlank(moduleName)) {
            return moduleName;
        }
        moduleName = ServletRequestUtils.getStringParameter(request, "module", DEFAULT_RAPIDCRM_MODULE);
        if (!raw) {
            String parentModule = request.getParameter("parent");
            if (EasyStringUtil.isNotBlank(parentModule)) {
                moduleName = parentModule + ":" + moduleName;
            }
        }
        return moduleName;
    }

    private RapidModuleModel getModuleModelBean(String moduleName) {
        RapidModuleModel moduleModel = null;
        try {
            moduleModel = getApplicationContext().getBean(moduleName, RapidModuleModel.class);
        } catch (Exception e) {
            log.error("Find RapidModuleModel name [ " + moduleName + " ] error: " + e.getMessage());
        }
        return moduleModel;
    }

    protected RapidModuleModel getModuleModelInstance(String moduleName) {
        RapidModuleModel moduleModel = getModuleModelBean(moduleName + "ModuleModel");
        if (moduleModel == null) {
            moduleModel = getModuleModelBean(RapidModuleModel.DEFAULT_MODULE_BEAN_NAME);
        }
        if (moduleModel == null) {
            throw new RuntimeGoingException("RapidActionView has not Module Model!");
        }
        return moduleModel;
    }
}
